import os
import sys
import tkinter as tk
from tkinter import messagebox, filedialog, ttk, simpledialog
from datetime import datetime, timedelta
from ConfigManager import ConfigManager
from WordContentExtractor import WordContentExtractor
from WordProcessor import WordProcessor
from Email import Email
from CustomDialog import CustomDialog
from LLMProcess import LLMProcess

class MainUI:
    def __init__(self, master):
        self.master = master
        master.title("Word AI助手")

        # 获取当前日期
        today = datetime.now()

        # 计算上周一的日期：先找到本周一，再减去7天
        last_monday = today - timedelta(days=today.weekday() + 7)

        # 计算上周五的日期：上周一加上4天
        last_friday = last_monday + timedelta(days=4)

        # 格式化日期为 YYYY/MM/DD
        self.last_monday_formatted = last_monday.strftime('%Y年%m月%d日')
        self.last_friday_formatted = last_friday.strftime('%Y年%m月%d日')
        self.week_number_monday_start = today.strftime("%W")  # 周一作为一周的开始

        # 计算本周一的日期
        start_of_week = today - timedelta(days=today.weekday())
        friday_of_week = start_of_week + timedelta(days=4)

        # 格式化日期为YYYYMMDD
        self.start_of_week_formatted = start_of_week.strftime('%Y年%m月%d日')
        self.friday_of_week_formatted = friday_of_week.strftime('%Y年%m月%d日')

        self.load_config()        

        # 设置UI容器的宽度和高度
        container_width = 300  # 最长按钮宽度的1.5倍
        container_height = 320  # 所有按钮之后的高度加上一些额外空间
        # 获取屏幕宽度和高度
        screen_width = master.winfo_screenwidth()
        screen_height = master.winfo_screenheight()

        # 计算窗口左上角的坐标
        x_position = (screen_width - container_width) // 2
        y_position = (screen_height - container_height) // 2

        # 设置窗口位置
        master.geometry(f"{container_width}x{container_height}+{x_position}+{y_position}")

        # 创建菜单栏
        menu_bar = tk.Menu(master, font=('宋体', 10))  # 设置菜单栏字体大小
        master.config(menu=menu_bar)

        # 添加“提示词配置”菜单项
        config_menu = tk.Menu(menu_bar, tearoff=0, font=('宋体', 10))  # 设置子菜单字体大小
        # config_menu.add_command(label="简讯提示词配置", command=self.show_brief_prompt_config_panel)        
        config_menu.add_command(label="大模型配置", command=self.show_model_config_panel)
        config_menu.add_command(label="恢复默认配置", command=self.confirm_restore)
        menu_bar.add_cascade(label="配置", menu=config_menu)

        # 创建按钮并设置统一的样式
        button_style = {'font': ('宋体', 16), 'width': 20, 'height': 1}

        self.reminder_button = tk.Button(master, text="发送简讯填写提醒邮件", command=self.send_reminder_email, **button_style)
        self.reminder_button.pack(pady=10)  # 下调位置

        # 新增按钮：简讯完整性检查
        self.integrity_check_button = tk.Button(master, text="简讯完整性检查", command=self.check_document_integrity, **button_style)
        self.integrity_check_button.pack(pady=10)

        # 新增按钮：简讯内容优化
        self.optimize_content_button = tk.Button(master, text="简讯内容优化", command=self.generate_optimized_document, **button_style)
        self.optimize_content_button.pack(pady=10)

        # 新增按钮：简讯摘要
        self.summary_button = tk.Button(master, text="简讯摘要", command=self.generate_summary, **button_style)
        self.summary_button.pack(pady=10)

        # 新增按钮：发送简讯邮件
        self.send_sms_button = tk.Button(master, text="发送简讯邮件", command=self.send_sms_email, **button_style)
        self.send_sms_button.pack(pady=10)
    def load_config(self):
        try:
            self.cm = ConfigManager()
            self.cm.check_config_version()
        except RuntimeError as e:
            messagebox.showerror("配置错误", f"加载配置失败，请找管理员解决: {e}")
            sys.exit(1)
    def confirm_restore(self):
        # 确认恢复默认设置的方法
        if messagebox.askyesno("确认", "确定要恢复默认配置吗？当前配置将被覆盖"):
            # 如果用户点击“是”，则调用ConfigManager的restore_default_config方法恢复默认配置
            self.cm.restore_default_config()
            # 重新获取最新的合并配置
            self.load_config()
            # 显示信息提示框，告知用户已恢复默认配置
            messagebox.showinfo("完成", "已恢复默认配置")

    def show_brief_prompt_config_panel(self):
        config_window = self.create_toplevel_window("简讯提示词配置", 1000, 750)

        # 添加配置项的输入框和标签
        tk.Label(config_window, text="文案检查提示词:").grid(row=0, column=0, padx=10, pady=10)
        self.check_prompt_text = tk.Text(config_window, width=115, height=15, wrap=tk.WORD)
        self.check_prompt_text.grid(row=0, column=1, padx=10, pady=10)
        self.check_prompt_text.insert(tk.END, self.cm.get_merged_config()['system_prompt']['brief']['check'].strip())

        # 添加纵向滚动条
        check_scrollbar = tk.Scrollbar(config_window, command=self.check_prompt_text.yview)
        check_scrollbar.grid(row=0, column=2, sticky='ns')
        self.check_prompt_text.config(yscrollcommand=check_scrollbar.set)

        tk.Label(config_window, text="文案优化提示词:").grid(row=1, column=0, padx=10, pady=10)
        self.optimization_prompt_text = tk.Text(config_window, width=115, height=15, wrap=tk.WORD)
        self.optimization_prompt_text.grid(row=1, column=1, padx=10, pady=10)
        self.optimization_prompt_text.insert(tk.END, self.cm.get_merged_config()['system_prompt']['brief']['optimization'].strip())

        # 添加纵向滚动条
        optimization_scrollbar = tk.Scrollbar(config_window, command=self.optimization_prompt_text.yview)
        optimization_scrollbar.grid(row=1, column=2, sticky='ns')
        self.optimization_prompt_text.config(yscrollcommand=optimization_scrollbar.set)

        tk.Label(config_window, text="文案摘要提示词:").grid(row=2, column=0, padx=10, pady=10)
        self.summary_prompt_text = tk.Text(config_window, width=115, height=15, wrap=tk.WORD)
        self.summary_prompt_text.grid(row=2, column=1, padx=10, pady=10)
        self.summary_prompt_text.insert(tk.END, self.cm.get_merged_config()['system_prompt']['brief']['summary'].strip())

        # 添加纵向滚动条
        summary_scrollbar = tk.Scrollbar(config_window, command=self.summary_prompt_text.yview)
        summary_scrollbar.grid(row=2, column=2, sticky='ns')
        self.summary_prompt_text.config(yscrollcommand=summary_scrollbar.set)

        # 添加保存按钮和关闭按钮
        button_frame = tk.Frame(config_window)
        button_frame.grid(row=3, column=0, columnspan=3, pady=10)

        save_button = tk.Button(button_frame, text="保存", command=self.save_brief_prompt_config, width=20, height=2)
        save_button.grid(row=0, column=0, padx=10)  # 放置在中间行的左侧

        close_button = tk.Button(button_frame, text="关闭", command=config_window.destroy, width=20, height=2)
        close_button.grid(row=0, column=1, padx=10)  # 放置在中间行的右侧

    def show_model_config_panel(self):
        config_window = self.create_toplevel_window("大模型配置", 480, 260)

        # 获取当前配置
        config = self.cm.get_merged_config()['model']

        # 创建输入框和标签
        tk.Label(config_window, text="Base URL:").grid(row=0, column=0, padx=10, pady=10, sticky='e')
        self.base_url_entry = tk.Entry(config_window, width=50)
        self.base_url_entry.grid(row=0, column=1, padx=10, pady=10)
        self.base_url_entry.insert(0, config['base_url'])

        tk.Label(config_window, text="API Key:").grid(row=1, column=0, padx=10, pady=10, sticky='e')
        self.api_key_entry = tk.Entry(config_window, width=50)  # 隐藏输入内容
        self.api_key_entry.grid(row=1, column=1, padx=10, pady=10)
        self.api_key_entry.insert(0, config['api_key'])

        tk.Label(config_window, text="模型名称:").grid(row=2, column=0, padx=10, pady=10, sticky='e')
        self.model_name_entry = tk.Entry(config_window, width=50)
        self.model_name_entry.grid(row=2, column=1, padx=10, pady=10)
        self.model_name_entry.insert(0, config['model_name'])

        # 流式输出开关（使用 IntVar 存储状态，0 表示关闭，1 表示开启）
        tk.Label(config_window, text="流式输出:").grid(row=3, column=0, padx=10, pady=10, sticky='e')
        self.streaming_var = tk.IntVar(value=1 if config['stream'] else 0)
        self.streaming_checkbox = tk.Checkbutton(config_window, variable=self.streaming_var)
        self.streaming_checkbox.grid(row=3, column=1, padx=10, pady=10, sticky='w')

        # 按钮区域
        button_frame = tk.Frame(config_window)
        button_frame.grid(row=4, column=0, columnspan=2, pady=20)

        save_button = tk.Button(button_frame, text="保存", command=self.save_model_config, width=10, height=1)
        save_button.pack(side=tk.LEFT, padx=10)

        test_button = tk.Button(button_frame, text="连通性测试", command=self.test_model_connection, width=10, height=1)
        test_button.pack(side=tk.LEFT, padx=10)

        close_button = tk.Button(button_frame, text="关闭", command=config_window.destroy, width=10, height=1)
        close_button.pack(side=tk.LEFT, padx=10)
    def create_toplevel_window(self, title, width=None, height=None):
        """
        创建一个带有图标的通用 Toplevel 窗口，并可选地设置大小和居中显示

        :param title: 窗口标题
        :param width: 窗口宽度
        :param height: 窗口高度
        :return: 创建的 Toplevel 对象
        """
        window = tk.Toplevel(self.master)
        window.title(title)

        # 设置窗口图标
        if getattr(sys, 'frozen', False):  # 判断是否被打包
            base_path = sys._MEIPASS
        else:
            base_path = os.path.join(os.path.dirname(__file__), '..')

        icon_path = os.path.join(base_path, 'resources', 'OfficeAI.ico')
        if os.path.exists(icon_path):
            window.iconbitmap(icon_path)

        # 如果提供了宽高，则设置窗口尺寸并居中
        if width and height:
            screen_width = window.winfo_screenwidth()
            screen_height = window.winfo_screenheight()
            x_position = (screen_width - width) // 2
            y_position = (screen_height - height) // 2
            window.geometry(f"{width}x{height}+{x_position}+{y_position}")

        return window
    
    def save_model_config(self):
        """
        保存大模型配置。
        """
        base_url = self.base_url_entry.get().strip()
        api_key = self.api_key_entry.get().strip()
        model_name = self.model_name_entry.get().strip()
        streaming = bool(self.streaming_var.get())

        config = self.cm.get_merged_config()

        # 更新配置文件中的model字段
        config['model']['base_url'] = base_url
        config['model']['api_key'] = api_key
        config['model']['model_name'] = model_name
        config['model']['stream'] = streaming

        self.cm.save_user_config(config)

        # 重新获取最新的合并配置
        self.load_config()

        # 关闭配置面板
        self.base_url_entry.master.destroy()

    def test_model_connection(self):
        """
        测试大模型的连接性。
        """
        base_url = self.base_url_entry.get().strip()
        api_key = self.api_key_entry.get().strip()
        model_name = self.model_name_entry.get().strip()
        streaming = bool(self.streaming_var.get())

        try:
            result = LLMProcess.getLLMTextResponse(model_name, api_key, base_url, 4096, 0.7, streaming, [{"role": "user", "content": "你好"}])        

            if result:
                messagebox.showinfo("测试结果", "连接成功！")
            else:
                messagebox.showerror("连接失败，请检查配置参数是否正确，或检查网络连通性，或检查账户是否有余额。")

        except Exception as e:
            messagebox.showerror("错误", f"连接测试失败: {str(e)}")
        
    def save_brief_prompt_config(self):
        """
        保存简讯提示词配置。

        从简讯提示词配置面板中获取用户输入的文案检查提示词、文案优化提示词和文案摘要提示词，
        更新配置文件中的相应字段，并将更新后的配置文件保存到磁盘。
        """
        # 获取输入框中的值
        check_prompt = self.check_prompt_text.get("1.0", tk.END).strip()
        optimization_prompt = self.optimization_prompt_text.get("1.0", tk.END).strip()
        summary_prompt = self.summary_prompt_text.get("1.0", tk.END).strip()

        config = self.cm.get_merged_config()

        # 更新配置文件中的custom字段
        config['system_prompt']['brief']['check'] = check_prompt
        config['system_prompt']['brief']['optimization'] = optimization_prompt
        config['system_prompt']['brief']['summary'] = summary_prompt

        self.cm.save_user_config(config)

        # 重新获取最新的合并配置
        self.load_config()

        # 关闭配置面板
        self.check_prompt_text.master.destroy()

    def send_reminder_email(self):        
        self._send__email()

    def send_sms_email(self):
        file_paths = []
        for i in range(2):
            if i == 0:
                message = "请选择邮件正文word文档"
            else:
                message = "请选择邮件附件word文档"

            file_path = filedialog.askopenfilename(
                title=message,
                filetypes=[("Word files", "*.docx")]
            )
            if not file_path:
                messagebox.showerror("错误", "请选择word文档！")
                return
            file_paths.append(file_path)

        if len(file_paths) != 2:
            messagebox.showerror("错误", "必须选择2个文档！")
        else:        
            self._send__email_attachments(file_paths[0],file_paths[1])

    def check_document_integrity(self):
        # 步骤1：选择Word文档
        r,files = self.select_word_documents()
        if r == False:
            return

        wordProcessor = WordProcessor()
        result = wordProcessor.check_document_integrity(files[0],files[1])
        CustomDialog(self.master, "文档完整性检查结果", result, type='info')

    def generate_optimized_document(self):
        file_path = filedialog.askopenfilename(
            title="请选择word文档",
            filetypes=[("Word files", "*.docx")]
        )
        if file_path:
            wordProcessor = WordProcessor()
            # 步骤3：文案优化
            result, msg = wordProcessor.generate_optimized_document(file_path)
            if not result:
                CustomDialog(self.master, "文案优化失败", msg, type='error')
            else:
                CustomDialog(self.master, "文案优化成功", msg, type='info')

    def generate_summary(self):
        file_path = filedialog.askopenfilename(
            title="请选择word文档",
            filetypes=[("Word files", "*.docx")]
        )
        if file_path:
            wordProcessor = WordProcessor()
            result, msg = wordProcessor.generate_summary(file_path)
            if not result:
                CustomDialog(self.master, "文案摘要失败", msg, type='error')
            else:
                CustomDialog(self.master, "文案摘要成功", msg, type='info')
        
    def select_word_documents(self):
        file_paths = []
        for i in range(2):
            if i == 0:
                message = "请选择旧word文档"
            else:
                message = "请选择新word文档"

            file_path = filedialog.askopenfilename(
                title=message,
                filetypes=[("Word files", "*.docx")]
            )
            if not file_path:
                messagebox.showerror("错误", "请选择两个文档！")
                return False,None
            file_paths.append(file_path)

        if len(file_paths) != 2:
            messagebox.showerror("错误", "必须选择新旧2个文档！")
            return False,None
        else:
            return True,file_paths

    def _send__email(self):
        try:
            mail_notification_subject = self.cm.get_merged_config()['mail']['notification']['subject'].strip()
            mail_notification_subject = mail_notification_subject.format(friday_date=self.friday_of_week_formatted)
            mail_notification_recipients = self.cm.get_merged_config()['mail']['notification']['recipients']
            mail_notification_cc_recipients = self.cm.get_merged_config()['mail']['notification']['cc_recipients']
            mail_notification_body = self.cm.get_merged_config()['mail']['notification']['body'].strip()
            mail_notification_body = mail_notification_body.format(friday_date=self.friday_of_week_formatted,monday_date=self.start_of_week_formatted)
        
            notificationEmail = Email()
            # 发送邮件
            notificationEmail.send_email(
                mail_notification_subject, 
                mail_notification_recipients, 
                mail_notification_cc_recipients,
                mail_notification_body
                )
            CustomDialog(self.master, "提示", "邮件发送成功！", type='info')
        except Exception as e:
            CustomDialog(self.master, "错误", f"发送邮件时发生错误: {str(e)}", type='error')

    def _send__email_attachments(self,body_file_path,attachment_file_path):        
        extractor = WordContentExtractor()
        html_content, images = extractor.extract_content(body_file_path)
        try:
            mail_weeklyreport_subject = self.cm.get_merged_config()['mail']['weeklyreport']['subject'].strip()
            mail_weeklyreport_subject = mail_weeklyreport_subject.format(week_number_monday_start=self.week_number_monday_start,
                                                                                last_monday=self.last_monday_formatted,
                                                                                last_friday=self.last_friday_formatted)
            mail_weeklyreport_recipients = self.cm.get_merged_config()['mail']['weeklyreport']['recipients']
            mail_weeklyreport_cc_recipients = self.cm.get_merged_config()['mail']['weeklyreport']['cc_recipients']

            notificationEmail = Email()
            # 发送邮件
            notificationEmail.send_email_with_attachments(
                mail_weeklyreport_subject,
                mail_weeklyreport_recipients, 
                mail_weeklyreport_cc_recipients, 
                html_content,
                images,
                [attachment_file_path])
            CustomDialog(self.master, "提示", "邮件发送成功！", type='info')
        except Exception as e:
            CustomDialog(self.master, "错误", f"发送邮件时发生错误: {str(e)}", type='error')
        finally:
            extractor.cleanup()

if __name__ == "__main__":
    root = tk.Tk()
    # 获取当前脚本文件的绝对路径
    script_dir = os.path.dirname(os.path.abspath(__file__))
    """ 获取打包后的资源绝对路径 """
    if getattr(sys, 'frozen', False):  # 判断是否被打包
        base_path = sys._MEIPASS
    else:
        base_path = os.path.join(script_dir, '..')
    icon_path = os.path.join(base_path, 'resources', 'officeAI.ico')  
    if os.path.exists(icon_path):
        root.iconbitmap(icon_path)
    app = MainUI(root)
    root.mainloop()